home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr44
/
xlib06p1.zip
/
XVSYNC.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-19
|
4KB
|
184 lines
#include "xdefs.h"
#define TIMER_VECT 0x08
#define PIC_CMD 0x20
#define NONSPEC_EOI 0x20
#define TIMER_MODE 0x34
#define TIMER_CONTROL 0x43
#define TIMER_0 0x40
#define LATCH_COUNT 0x00
#define INT_IN_ADVANCE 0x100
#define DOS_GETVECT 0x3500
#define DOS_SETVECT 0x2500
WORD _TicksPerSecond;
unsigned long _VsyncIntTicks;
WORD _VsyncPeriod;
WORD ClockRate;
WORD ClockCounter;
void ( __interrupt __far *UserVsyncHandler )();
WORD InUserHandler;
void * LocalStack;
WORD ElapsedVrts;
WORD VrtsToSkip = 1;
inline void WaitVsyncStart(
void
)
{
while( inp( INPUT_STATUS_0 ) & 0x08 );
while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
}
int get_vsync_period(
void
)
{
outp( TIMER_CONTROL, TIMER_MODE );
outp( TIMER_0, 0 );
outp( TIMER_0, 0 );
//now wait for the vertical sync
WaitVsyncStart();
outp( TIMER_CONTROL, LATCH_COUNT );
int iBegin = inp( TIMER_0 );
iBegin += ( inp( TIMER_0 ) << 8 );
//now iBegin = 65536 - clicks, so wait for the vsync again
WaitVsyncStart();
outp( TIMER_CONTROL, LATCH_COUNT );
int iEnd = inp( TIMER_0 );
iEnd += ( inp( TIMER_0 ) << 8 );
//now iEnd = 65536 - clicks
//now return iBegin - iEnd to get the change in clicks
return( iBegin - iEnd );
}
void __interrupt __far vsync_int(
void
)
{
++VsyncIntTicks;
++ElapsedVrts;
//if there's something to do, do it.
if ( ElapsedVrts >= VrtsToSkip ) {
if ( StartAddressFlag != 0 ) {
outpw( CRTC_INDEX, WaitingStartLow );
outpw( CRTC_INDEX, WaitingStartHigh );
}
}
//now stop the clock so we can re-sync
_disable();
outp( TIMER_CONTROL, TIMER_MODE );
outp( TIMER_0, 255 );
outp( TIMER_0, 255 );
//now wait for the vsync again...
while( inp( INPUT_STATUS_0 ) & 0x08 );
//now restart yon clock...
outp( TIMER_CONTROL, TIMER_MODE );
outp( TIMER_0, ClockRate & 0xff );
outp( TIMER_0, ClockRate >> 8 );
//more checks on "if there's something to do..."
if ( ElapsedVrts >= VrtsToSkip ) {
if ( StartAddressFlag != 0 ) {
ElapsedVrts = 0;
outp( AC_INDEX, WaitingPelPan & 0xff );
outp( AC_INDEX, WaitingPelPan >> 8 );
StartAddressFlag = 0;
}
}
//check for a palette update
if ( VsyncPaletteCount != 0 ) {
outp( DAC_WRITE_INDEX, VsyncPaletteStart & 0xff );
BYTE * pbDacData = VsyncPaletteBuffer + VsyncPaletteStart;
for ( int i = 0; i < VsyncPaletteCount; ++i ) {
outp( DAC_DATA, *pbDacData++ );
outp( DAC_DATA, *pbDacData++ );
outp( DAC_DATA, *pbDacData++ );
}
VsyncPaletteCount = 0;
}
//check for a mouse update
if ( MouseRefreshFlag != 0 ) {
MouseVsyncHandler();
}
//check for a user vsync handler
if ( UserVsyncHandler != NULL ) {
if ( InUserHandler == 0 ) {
SetStack(...)
_enable();
UserVsyncHandler();
_disable();
InUserHandler = 0;
}
}
//now simulate the 18.2 Hz timer handler
ClockCounter += VsyncPeriod;
if ( ClockCounter >= 65536 ) {
_enable();
OldTimerInt();
ClockCounter -= 65536;
}
outp( PIC_CMD, NONSPEC_EOI );
_enable();
}
void x_install_vsync_handler(
int iVrtSkipCount
)
{
if ( iVrtSkipCount <= 0 ) {
iVrtSkipCount = 0;
}
VrtsToSkip = iVrtSkipCount;
ElapsedVrts = 0;
if ( VsyncHandlerActive == TRUE ) {
return;
}
int iPeriod = get_vsync_period;
VsyncPeriod = iPeriod;
iPeriod -= INT_IN_ADVANCE;
ClockRate = iPeriod;
TicksPerSecond = 13352 / VsyncPeriod;
_disable();
OldTimerInt = dos_getvect( TIMER_VECT );
VsyncHandlerActive = TRUE;
dos_setvect( TIMER_VECT, vsync_int );
outp( TIMER_CONTROL, TIMER_MODE );
outp( TIMER_0, ClockRate & 0xff );
outp( TIMER_0, ClockRate >> 8 );
}
void x_remove_vsync_handler(
void
)
{
if ( VsyncHandlerActive == FALSE ) {
return;
}
_disable();
dos_setvect( TIMER_VECT, OldTimerInt );
outp( TIMER_CONTROL, TIMER_MODE );
outp( TIMER_0, 0 );
outp( TIMER_0, 0 );
_enable();
}
void x_set_user_vsync_handler(
void ( __interrupt __far *pvHandlerProc )()
)
{
_disable();
UserVsyncHandler = pvHandlerProc;
_enable();
}